<?php

use App\Models\Auth\UserParkingLot;
use App\Models\Setting\Setting;

if (!function_exists('requestSource')) {

    function requestSource()
    {
        return request()->header('Source') ?: \App\Models\Common\Constant::SOURCE_ADMIN;
    }
}

if (!function_exists('admin')) {
    /**
     * @return \Illuminate\Contracts\Auth\Authenticatable|\App\Models\Auth\User|null
     */
    function admin()
    {
        if ($admin = auth('admin')->user()) {
            $admin->reassignPermissions();
        }
        return $admin;
    }
}

if (!function_exists('app_user')) {
    /**
     * @return \Illuminate\Contracts\Auth\Authenticatable|\App\Models\App\AppUser|null
     */
    function app_user()
    {
        return auth('app')->user();
    }
}

if (function_exists('app_user') && !function_exists('appUser')) {
    /**
     * @return \Illuminate\Contracts\Auth\Authenticatable|\App\Models\App\AppUser|null
     */
    function appUser()
    {
        return app_user();
    }
}

if (!function_exists('getParkingLotID')) {

    /**
     * @return string
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function getParkingLotID(bool $isFromApp = false, bool $exceptionIgnore = false): string
    {
        $parkingLotID = '';

        if ($isFromApp) {
            if ($headerParkingLotID = request()->header('Parking-Lot-Id')) {
                if (\App\Models\ParkingLot\ParkingLot::find($headerParkingLotID)) {
                    $parkingLotID = $headerParkingLotID;
                }
            }
        } else {
            $user = admin();

            if (\App\Models\Auth\User::IDENTITY_MERCHANT === optional($user)->identity) {
                $parkingLotID = optional(UserParkingLot::where('user_id', $user->id)->first())->parking_lot_id;
            } else {
                if (app()->has('parking_lot_id')) {
                    $parkingLotID = app()->get('parking_lot_id');
                } elseif ($headerParkingLotID = request()->header('Parking-Lot-Id')) {
                    $scopeParkingLotIDs = optional($user)->parkingLotIDs ?: [];
                    if (in_array($headerParkingLotID, $scopeParkingLotIDs, true)) {
                        $parkingLotID = $headerParkingLotID;
                    }
                }
            }
        }

        if (!$parkingLotID && !$exceptionIgnore) {
            throw new \InvalidArgumentException('获取当前环境车场ID失败');
        }
        return $parkingLotID;
    }
}

if (!function_exists('sourceParkingLot')) {

    /**
     * @return string
     */
    function sourceParkingLot(): string
    {
        return request()->hasHeader('Parking-Lot-Id');
    }
}

if (!function_exists('getMerchantID')) {

    /**
     * @return string
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function getMerchantID(bool $exceptionIgnore = false): string
    {
        $merchantID = '';

        $user = admin();

        if (\App\Models\Auth\User::IDENTITY_MERCHANT === $user->identity) {
            $merchantID = optional(\App\Models\Merchant\MerchantUser::where('user_id', $user->id)->first())->merchant_id;
        } else {
            if (app()->has('merchant_id')) {
                $merchantID = app()->get('merchant_id');
            } elseif ($headerMerchantID = request()->header('Merchant-Id')) {
                $parkingLotID = optional(\App\Models\Merchant\Merchant::find($headerMerchantID))->parking_lot_id;
                $scopeParkingLotIDs = optional($user)->parkingLotIDs ?: [];
                if (in_array($parkingLotID, $scopeParkingLotIDs, true)) {
                    $merchantID = $headerMerchantID;
                }
            }
        }

        if (!$merchantID && !$exceptionIgnore) {
            throw new \InvalidArgumentException('获取当前环境商户ID失败');
        }
        return $merchantID;
    }
}

if (!function_exists('sourceMerchant')) {

    /**
     * @return string
     */
    function sourceMerchant(): string
    {
        return request()->hasHeader('Merchant-Id');
    }
}

if (!function_exists('joinStr')) {

    function joinStr(array $signArr, string $tag = '&'): string
    {
        $appendStr = '';
        foreach ($signArr as $key => $item) {
            if (is_array($item)) {
                $item = json_encode($item);
            }

            if ($key !== 'sign') {
                $appendStr .= $key . '=' . $item . $tag;
            }
        }
        return trim($appendStr, $tag);
    }
}

if (!function_exists('joinStrWithoutNull')) {

    function joinStrWithoutNull(array $signArr, string $tag = '&'): string
    {
        $appendStr = '';
        ksort($signArr);
        foreach ($signArr as $key => $value) {

            if ($value === null || $value === '') {
                continue;
            }

            if (is_array($value)) {
                $value = json_encode($value);
            }

            if ($key !== 'sign') {
                $appendStr .= $key . '=' . $value . $tag;
            }
        }
        return trim($appendStr, $tag);
    }
}

if (!function_exists('arr2xml')) {

    function arr2xml($arrDat): string
    {
        $xml = '<xml>';
        foreach ($arrDat as $key => $val) {
            $xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
        }
        $xml .= '</xml>';
        return $xml;
    }
}

if (!function_exists('xmlEncode')) {

    function xmlEncode(string $xmlResp): string
    {
        $pattern = '/<\?xml[^>]*encoding=(["\'])(.*?)\1[^>]*\?>/i';
        preg_match($pattern, $xmlResp, $matches);
        if (isset($matches[2])) {
            return $matches[2];
        }

/*        if (preg_match("/<?xml[^>]* encoding=\"(.*)\"[^>]* ?>/i", $xmlResp, $arr)) {*/
//            return strtoupper($arr[1]);
//        }
        return "";
    }
}

if (!function_exists('xml2Arr')) {

    function xml2Arr(string $xmlResp): array
    {
        $arrResp = [];
        if ($xmlResp) {
            libxml_disable_entity_loader(true);
            $xml = simplexml_load_string($xmlResp);
            $encode = xmlEncode($xmlResp);
            if ($xml && $xml->children()) {
                foreach ($xml->children() as $node) {
                    if ($node->children()) {
                        $k = $node->getName();
                        $nodeXml = $node->asXML();
                        $v = substr($nodeXml, strlen($k) + 2, strlen($nodeXml) - 2 * strlen($k) - 5);
                    } else {
                        $k = $node->getName();
                        $v = (string)$node;
                    }

                    if ($encode != "" && $encode != "UTF-8") {
                        $k = iconv("UTF-8", $encode, $k);
                        $v = iconv("UTF-8", $encode, $v);
                    }
                    $arrResp[$k] = $v;
                }
            }
        }
        return $arrResp;
    }
}

if (!function_exists('explode2Arr')) {

    function explode2Arr($rawStr = null, string $separator = ','): array
    {
        if (!$rawStr) {
            return [];
        }

        if (!is_string($rawStr)) {
            return $rawStr;
        }

        $rawStr = str_replace('，', ',', $rawStr);
        $strArr = array_unique(array_filter(explode($separator, $rawStr)));
        return array_map(function ($value) {
            if (is_string($value)) {
                $value = trim($value);
            }
            return $value;
        }, $strArr);
    }
}

if (!function_exists('format_uuid')) {
    /**
     * 格式化 uuid.
     *
     * @param $uuid
     * @param bool $addLodash 是添加 - 还是去掉， true or false
     */
    function format_uuid($uuid, $addLodash = true): string
    {
        return $addLodash ? implode('-', [
            substr($uuid, 0, 8),
            substr($uuid, 8, 4),
            substr($uuid, 12, 4),
            substr($uuid, 16, 4),
            substr($uuid, 20),
        ]) : str_replace('-', '', $uuid);
    }
}

if (!function_exists('safeInt')) {
    function safeInt($value): int
    {
        return intval(strval($value));
    }
}

if (!function_exists('sec2time')) {
    //将秒（非时间戳）转化成 ** 小时 ** 分
    function sec2time($sec, $m = '分')
    {
        $sec = round($sec / 60);
        if ($sec >= 60) {
            $hour = floor($sec / 60);
            $min = $sec % 60;
            $res = $hour . '小时';
            0 != $min && $res .= $min . $m;
        } else {
            $res = $sec . $m;
        }

        return $res;
    }
}

if (!function_exists('secondsToDHMS')) {
    //将秒（非时间戳）转化成 ** 小时 ** 分
    function secondsToDHMS($seconds)
    {
        // 计算天数
        $days = floor($seconds / 86400);
        // 从总秒数中减去已经计算过的天数所对应的秒数
        $seconds %= 86400;

        // 计算小时数
        $hours = floor($seconds / 3600);
        // 从剩余的秒数中减去已经计算过的小时数所对应的秒数
        $seconds %= 3600;

        // 计算分钟数
        $minutes = floor($seconds / 60);
        // 剩余的就是秒数
        $seconds %= 60;

        // 创建结果字符串
        $result = "";
        if ($days > 0) {
            $result .= "{$days}天";
        }
        if ($hours > 0) {
            $result .= "{$hours}小时";
        }
        if ($minutes > 0) {
            $result .= "{$minutes}分";
        }
        $result .= "{$seconds}秒";

        return $result;
    }
}

if (!function_exists('check_date')) {
    /**
     * 校验日期格式是否正确
     */
    function check_date($date, $formats = ['Y-m-d', 'Y/m/d', 'Y-m-d H:i:s']): bool
    {
        $unix = strtotime(strval($date));
        if (!$unix) {
            return false;
        }

        foreach ($formats as $format) {
            if (date($format, $unix) == $date) {
                return true;
            }
        }
        return false;
    }
}

if (!function_exists('match_chinese')) {
    /**
     * 过滤字符串，仅保留汉字、数字、英文
     * @param $chars
     * @param string $encoding
     * @return string
     */
    function match_chinese($chars, $encoding = 'utf8')
    {
        $pattern = ($encoding == 'utf8') ? '/[\x{4e00}-\x{9fa5}a-zA-Z0-9]/u' : '/[\x80-\xFF]/';
        preg_match_all($pattern, $chars, $result);
        $temp = join('', $result[0]);
        return $temp;
    }
}

if (!function_exists('check_car_no')) {
    /**
     * 校验车牌号格式是否正确
     * @param $carNo
     * @return bool
     */
    function check_car_no($carNo)
    {
        $carNo = strval($carNo);
        //参数判断
        if (empty($carNo)) {
            return false;
        }

//        $str = match_chinese($carNo);
//        if ($carNo !== $str) {
//            return false;
//        } else {
//            return true;
//        }
        if (strpos($carNo, ' ') !== false) {
            return false;
        }

        if (strpos($carNo, ',') !== false) {
            return false;
        }
        return true;

        //匹配民用车牌和使馆车牌
        //判断标准
        //1.第一位为汉子省份缩写
        //2.第二位为大写字母城市编码
        //3.后面是5位仅含字母和数字的组合
        $regular = '/^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使电]{1}[A-Z]{1}[0-9A-Z]{5}$/u';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }
        //匹配特种车牌(挂,警,学,领,港,澳)
        $regular = '/^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新电]{1}[A-Z]{1}[0-9A-Z]{4}[挂警学领港澳电]{1}$/u';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }
        //匹配武警车牌
        $regular = '/^WJ[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新电]?[0-9A-Z]{5}$/ui';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }
        //匹配军牌
        $regular = '/[A-Z]{2}[0-9]{5}$/';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }
        //匹配新能源车辆6位车牌
        //小型新能源车
//        $regular = '/^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新]{1}[A-Z]{1}[DF]{1}[0-9a-zA-Z]{5}$/u';
        $regular = '/^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新电]{1}[A-Z]{1}[0-9A-Z]{6}$/u';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }
        //大型新能源车
        $regular = '/^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新电]{1}[A-Z]{1}[0-9A-Z]{5}[DF]{1}$/u';
        preg_match($regular, $carNo, $match);
        if (isset($match[0])) {
            return true;
        }

        return false;
    }
}

if (!function_exists('addRealMonths')) {
    /**
     * 添加自然月
     * @param $began
     * @param $months
     * @return Carbon\Carbon
     */
    function addRealMonths($began, $months)
    {
        $beganAt = Carbon\Carbon::parse($began);
        $expiredAt = (clone $beganAt)->addMonthsNoOverflow($months);

        // 月底处理
        if ($beganAt->toDateString() === Carbon\Carbon::parse($beganAt->year . '-' . $beganAt->month . '-01')->endOfMonth()->toDateString()) {
            $date = (clone $expiredAt)->endOfMonth()->toDateString();
            $time = (clone $expiredAt)->toTimeString();
            $expiredAt = Carbon\Carbon::parse($date . ' ' . $time);
        } else {
            if (in_array($beganAt->toDateString(), [$beganAt->year . '-01-29', $beganAt->year . '-01-30'])) {
                $date = (clone $expiredAt)->endOfMonth()->toDateString();
                $time = (clone $expiredAt)->toTimeString();
                $expiredAt = Carbon\Carbon::parse($date . ' ' . $time);
            } else {
                $expiredAt = $expiredAt->subDay();
            }
        }

        return $expiredAt;
    }
}

if (!function_exists('getRealClientIp')) {
    function getRealClientIp()
    {
        return (request()->header('remoteip') ?: request()->header('x-forwarded-for')) ?: request()->getClientIp();
    }
}

if (!function_exists('GetRandStr')) {
    function GetRandStr($length)
    {
        //字符组合
        $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $len = strlen($str) - 1;
        $randStr = '';
        for ($i = 0; $i < $length; $i++) {
            $num = mt_rand(0, $len);
            $randStr .= $str[$num];
        }
        return $randStr;
    }
}

if (!function_exists('batchUpdate')) {

    /**
     * @param string $table
     * @param array $dataSet
     * @param string $key
     * @return string
     * 批量更新
     */
    function batchUpdate(string $table, array $dataSet, string $key = 'id'): string
    {
        if (count($dataSet) === 0) {
            return false;
        }
        $sql = 'UPDATE ' . $table . ' as t1 JOIN (' . PHP_EOL;
        $values = '';
        $keys = array_keys(Arr::first($dataSet));
        foreach ($dataSet as $row) {
            if (!isset($row[$key])) {
                continue;
            }

            $values && $values .= PHP_EOL . ' UNION ' . PHP_EOL;
            $values .= 'SELECT ';

            foreach ($row as $k => $rowData) {
                if (($k === 'deleted_at') && !$rowData) {
                    $values .= ' null  AS ' . $k . ',';
                } elseif (($k === 'expired_at') && !$rowData) {
                    $values .= ' null  AS ' . $k . ',';
                } else {
                    $values .= "'" . $rowData . "' AS " . $k . ',';
                }
            }
            $values = trim($values, ',');
        }
        if ($values) {
            $sql .= $values . ') t2 USING(' . $key . ') SET ';

            foreach ($keys as $value) {
                if (strtolower($value) === strtolower($key)) {
                    continue;
                }
                $sql .= 't1.' . $value . ' = t2.' . $value . ',';
            }
            return trim($sql, ',');
        }
        return '';
    }
}

if (!function_exists('get_custom_settings')) {
    function get_custom_settings()
    {
//        $host = $baseKey . (request()->getHttpHost() ?: 'none');
        $data = [
            'system_name' => '壹泊车智慧系统',
            'site_keyword' => '',
            'site_description' => '',
            'site_icp' => '',
        ];

        $cacheKey = 'site_settings';

        // !\Cache::has($cacheKey) &&
        if (\Illuminate\Support\Facades\Schema::hasTable('settings')) {
            $settings = Setting::where('category', Setting::CATEGORY_SITE)->pluck('value', 'key')->toArray();
            if ($settings) {
                foreach ($settings as $key => $value) {
                    if ('name' === $key) {
                        $data['system_name'] = $value;
                    }
                    if ('keyword' === $key) {
                        $data['site_keyword'] = $value;
                    }
                    if ('description' === $key) {
                        $data['site_description'] = $value;
                    }
                    if ('icp' === $key) {
                        $data['site_icp'] = $value;
                    }
                }
//                \Cache::put($cacheKey, $data, now()->addMinutes(30));
            } else {
//                \Cache::put($cacheKey, $data, now()->addMinutes(10));
            }
        } else {
//            $data = \Cache::get($cacheKey);
        }

        return $data;
    }
}

